/**
 * @author Javier Guaje <jrguajeg@gmail.com>
 */

package co.edu.unal.satacredito.database.dao;

import co.edu.unal.satacredito.database.entity.FileLog;
import co.edu.unal.satacredito.database.exception.NonexistentEntityException;
import co.edu.unal.satacredito.database.exception.UnreachableHostException;
import com.google.code.morphia.Datastore;
import com.google.code.morphia.Key;
import com.google.code.morphia.mapping.Mapper;
import com.google.code.morphia.query.Query;
import com.google.code.morphia.query.UpdateOperations;
import com.google.code.morphia.query.UpdateResults;
import com.mongodb.WriteResult;
import java.util.Date;
import java.util.List;
import java.util.logging.Level;
import java.util.logging.Logger;
import org.bson.types.ObjectId;

public class FileLogMongoDao {
    
    private static final String FILE_LOG_ID = "_id";
    private static final String FILE_ID = "fileId";
    private static final String BRAND = "brand";
    private static final String ESTABLISHMENT = "establishment";
    private static final String DATE = "date";
    private static final String STATE = "state";
    
    private Datastore mDs;
    
    public FileLogMongoDao(Datastore datastore) {
        this.mDs = datastore;
    }
    
    public ObjectId create(FileLog newFile) throws UnreachableHostException {
        Key<FileLog> key = mDs.save(newFile);
        if (key == null) {
            throw new UnreachableHostException(UnreachableHostException.ERROR_MESSAGE);
        }
        return (ObjectId) key.getId();
    }
    
    public boolean delete(ObjectId id) throws UnreachableHostException {
        try {
            Query<FileLog> query = mDs.find(FileLog.class).field(Mapper.ID_KEY).equal(id);
            FileLog file = query.get();
            if (file == null) {
                throw new NonexistentEntityException(NonexistentEntityException.ERROR_MESSAGE);
            }
            WriteResult result = mDs.delete(FileLog.class, id);
            if (result == null) {
                throw new UnreachableHostException(UnreachableHostException.ERROR_MESSAGE);
            }
            return true;
        } catch (NonexistentEntityException nee) {
            Logger.getLogger(FileLogMongoDao.class.getName()).log(Level.SEVERE, null, nee);
            return false;
        }
    }
    
    public boolean update(ObjectId id, FileLog newFile) throws UnreachableHostException {
        try {
            Query<FileLog> query = mDs.find(FileLog.class).field(Mapper.ID_KEY).equal(id);
            FileLog file = query.get();
            if (file == null) {
                throw new NonexistentEntityException(NonexistentEntityException.ERROR_MESSAGE);
            }
            UpdateOperations<FileLog> update = mDs.createUpdateOperations(FileLog.class);
            update.set(FILE_ID, newFile.getFileId());
            update.set(BRAND, newFile.getBrand());
            update.set(ESTABLISHMENT, newFile.getEstablishment());
            update.set(DATE, newFile.getDate());
            update.set(STATE, newFile.getState());
            UpdateResults<FileLog> result = mDs.update(query, update);
            if (result == null) {
                throw new UnreachableHostException(UnreachableHostException.ERROR_MESSAGE);
            }
            return true;
        } catch (NonexistentEntityException nee) {
            Logger.getLogger(FileLogMongoDao.class.getName()).log(Level.SEVERE, null, nee);
            return false;
        }
    }
    
    public FileLog findById(ObjectId id) throws UnreachableHostException {
        return mDs.find(FileLog.class).field(Mapper.ID_KEY).equal(id).get();
    }
    
    public FileLog findByFileId(ObjectId id) throws UnreachableHostException {
        return mDs.find(FileLog.class).field(FILE_ID).equal(id).get();
    }
    
    public List<FileLog> findByDateRange(Date initDate, Date endDate) throws UnreachableHostException {
        Query<FileLog> query = mDs.find(FileLog.class);
        query.field(DATE).greaterThanOrEq(initDate);
        query.field(DATE).lessThanOrEq(endDate);
        return query.asList();
    }
}